הכלה המשך בדף עבודה הקודם, הדגשנו את ההכלה של אובייקט אחד מוכל בתוך אובייקט אחר. ישנו עוד סוג של הכלה שהיא גם מאוד נפוצה וזו הכלה של אוסף אובייקטים בתוך אובייקט אחד. כדי להדגים את זה נגדיר חפיסת קלפים. מה זה חפיסת קלפים? אוסף של קלפים כדי להדגים את זה, נגדיר קלף וחפיסת קלפים השלם: חפיסה והחלקים שלה : אוסף של קלפים קלפים * חפיסה קלף כיצד נוכל לתרגם את זה לקוד: מחלקת קלף קלפים של האפשרים הסוגים הגדרת ;// CLUBS enum Suit SPADES, DIAMONDS, HEARTS, class Card צורה suit;// private Suit ערך value;// private int public Card(Suit suit, int value) this.suit = suit; this.value = value > 1 && value < 15? value : 2; public Card(int value, Suit suit) : this(suit, value) public Suit GetSuit() return this.suit; public int GetValue() return this.value; public bool Ace() return value == 14; public string ValueName() string s; switch (value) case 11: s="jack"; case 12: s= "QUEEN"; case 13: s = "KING"; case 14: s = "ACE"; default: s = value.tostring(); return string.format("0 of 1", ValueName(),suit.ToString());
ומחלקת חפיסה class Deck private Card[] cards; public int count; מלאה חפיסה היוצרת בונה שיטה // Deck() public cards = new Card[52]; count =0; for (Suit s = Suit.SPADES; s <= Suit.CLUBS; s++) for (int i = 2; i < 15; i++) cards[count++] = new Card(s, i); Shuffle(); ריקה חפיסה המכינה בונה שיטה //(x public Deck(int cards = new Card[52]; count = 0; public void Shuffle() Random rnd = new Random(); for (int i = 0; i < 30; i++) int x = rnd.next(count); int y = rnd.next(count); Card c = cards[x]; cards[x] = cards[y]; cards[y] = c; public Card Remove() return cards[--count]; public void Add(Card c) for (int i = count; i > 0; i--) cards[i] = cards[i - 1]; cards[0] = c; count++; string s=""; for (int i = 0; i < count; i++) s+= string.format("0:50 if (i%3==2) s+="\n"; return s; public bool IsEmpty() return count == 0; ",cards[i]); בתוך החפיסה יש שתי שיטות בונות: שיטה אחת היוצרת חפיסה מלאה עם 52 קלפים שיטה שניה היוצרת חפיסה ריקה מקלפים כאשר אפשר להשתמש בשיטה Add כדי להוסיף קלפים לחפיסה. עבור כל שיטה ציינתי תיאור והנחות )באילו תנאים הפעולה אכן תעבוד(
שיטה: Shuffle )ערבב את הקלפים( שבוחרת שתי קלפים רנדומלים ומחליף במקומות. את זה עושים מס' רב של פעמים ואז מקבלים חפיסה מעורבבת. חייב להיות קלפים בחפיסה שיטה: Remove מורידה את הקלף שנמצא למעלה )ובו זמנית מקטינה את מס' הקלפים בחפיסה.( ומחזירה את הקלף שהוריד הפעולה לא תעבוד אם אין קלפים בחפיסה שיטה : Add מוסיפה את הקלף לצד השני. המערכת מזיזה את כל הקלפים מקום אחד קדימה ולבסוף מכניס את הקלף למקום הראשון. הפעולה לא תעבוד אם יש חפיסה מלאה שיטה : IsEmpty() מחזירה אמת אם נשארו קלפים בחפיסה כעת נוכל להגדיר עוד מחלקה שתעזור לנו לבנות משחק קלפים "מלחמה" )המשחק תהיה פשוטה ללא מצב של "מלחמה" כלומר מצב ששני השחקנים שמים אותו מספר( class Player שם השחקן name;// private string הקלפים של השחקן deck;// private Deck public Player (string name) הוספת שם name;// this.name = יצירת חפיסה ריקה//;( Deck(0 deck = new public string GetName() return this.name; public Card ThrowCard() return deck.remove(); public void TakeCard(Card c) deck.add(c); return name + "\n" + deck.tostring(); public bool HasCards() return!deck.isempty(); יש לנו מחלקת שחקן שמוגדר עבורו שם ואילו קלפים יש לו ביד. שיטה הבונה: מקבלת שם ויוצרת חפיסה ריקה פעולה GetName() המחזירה את שם השחקן פעולה ThrowCard() אשר זורקת מהיד קלף בראש החפיסה שהשחקן מחזיק ביד. הפעולה עובדת בתנאי שיש קלפים ביד השחקן
פעולה (Card) TakeCard אשר מכניסה לסוף החפיסה קלף חדש הפעולה עובדת בתנאי שלא כל הקלפים נמצאים ביד הקלף פעולה HasCards() ומחזירה אמת אם יש לשחקן עוד קלפים שימו לב כיצד ממשים את הפעולות של השחקן. השחקן אינו כותב את הלוגיקה אלא משתמש בפעולות הקיימות כבר במחלקה שהיא מכילה : Deck כעת נכתוב מחלקה.Game המחלקה החדשה אינה משהו מוחשי כמו שחקן / קלף / חפיסה אלא משהו מופשט, מעין מנהל שמנווט בין המחלקות ומרכז את כללי המשחק תוך שימוש במחלקות המוכלות. תרשים מחלקות של המשחק Game 2 Player 2 Card * תיאור הקשרים המשחק מכיל 2 שחקנים ו- 2 קלפי השולחן Game has 2 players Deck Game has 2 Cards המשחק משתמש בחפיסה )בהתחלת המשחק( לשחקן יש חפיסת קלפים Player has a Deck of Cards לחפיסה יש עד 52 קלפים Deck has Cards
class Game 1 שחקן player1;// private Player 2 שחקן player2;// private Player השולחן על 1 שחקן של קלף //;c1 Card השולחן על 2 שחקן של קלף //;c2 Card public Game(string n1, string n2) חדשה חפיסה פתיחת Deck();// Deck deck = new player1 = new Player(n1); player2 = new Player(n2); c1 = null; c2 = null; שחקנים שני בין החפיסה קלפי כל חלוקת (!deck.isempty())// while player1.takecard(deck.remove()); if (!deck.isempty()) player2.takecard(deck.remove()); public void MakeMove() c1 = player1.throwcard(); c2 = player2.throwcard(); Console.WriteLine("Player one 0 - Player two 1", c1,c2); public void FinishMove() if (c1!= null) if (c1.getvalue() > c2.getvalue()) player1.takecard(c1); player1.takecard(c2); else player2.takecard(c1); player2.takecard(c2); c1 = null; c2 = null; public bool Won() return (!player1.hascards()!player2.hascards()); public Player Winner() if (!player1.hascards()) return player2; else if (!player2.hascards()) return player1; return null;
פעולת המחלקה Game פעולה בונה : מאתחלת חפיסה מלאה, מאתחלת שני שחקנים )עם שם שמתקבל בפעולה הראשי( ומחלקת את הקלפים בין השחקנים פעולה זריקת הקלפים MakeMove() : כל אחד מהשחקנים זורק את הקלף הראשון שלו על השולחן חייבים להיות לשני השחקנים קלפים וסיימו את המהלך הקודם פעולה סיום המהלך FinishMove() בודק מי "ניצח" )למי יש את הערך הגבוה( ומעביר את הקלפים למנצח חייבים להיות שני קלפים על השולחן פעולה בדיקת מצב ניצחון: Won() מחזירה אמת אם יש שחקן מנצח פעולה בדיקת מי המנצח Winner() פעולה המחזירה את השחקן שניצח את המשחק )כלומר לא השחקן שנותר ללא קלפים חייב להיות מצב שאחד השחקנים ניצח כעת יש לנו משחק וכל מה שאנו צריכים זה תוכנית ראשית שיאפשר לשחקנים לשחק class Program static void Main(string[] args) Game game = new Game("Ploni", "Almoni"); char c = 'm'; while (!game.won()&& c== 'm') game.makemove(); game.finishmove(); c = Console.ReadKey().KeyChar; if (game.won()) Console.WriteLine("The Winner is: 0", game.winner().getname()); Console.ReadKey(); בשיטה Main הגדרנו משחק עם שמות של שני שחקנים. המשחק ממשיך כל עוד מקישים m והמשחק לא מסתיים. לבסוף, אם המשחק מסתיים בגלל שניצח, מדפיסים את שם המנצח
תרגיל 1: שאלת בגרות תשס"ז באתר "הסקר השבועי" מתפרסם בכל שבוע סקר חדש ובו שאלה אחת. האתר שומר את 50 הסקרים האחרונים, כולל הסקר החדש. הנתונים בעבור כל סקר הם: תאריך הפרסום שלו, השא לה הנשאלת בו, ארבע תשובות אפשריות לשאלה, ובעבור כל תשובה מספר המשתתפים שבחרו בה. א. הגדר את המחלקות הנדרשות לצורך מימוש האתר "הסקר השבועי". בעבור כל אחת של המחלקות שאתה מגדיר: i. כתוב מה היא מייצגת. #C כתוב את הכותרת שלה ב-.ii.iii הגדר את התכונות שלה ב- #C. כתוב תיעוד עבור כל תכונה ב. ניהול האתר "הסקר השבועי" כולל: הוספת סקר חדש. הדפסת השאלה של הסקר החדש, והדפסת ארבע התשובות האפשריות עליה. קליטת תשובה שבחר משתתף בסקר החדש, ועדכון מספר המשתתפים שבחרו בתשובה זו. קליטת תאריך של פרסום הסקר ובעבור שאלת הסקר יש להדפיס מס' המשתתפים שבחרו בכל אחד מהתשובות מה היתה התשובה שנבחרה על ידי מס' הגדול ביותר של משתתפים הגדר את הפעולות הנדרשות לניהול ה"אתר הסקר השבועי" הנח שמוגדרים עבור כל אחד מהמאפיינים פעולות set / get מהמחלקות שהגדרת בסעיף א' בעבור כל אחד מהפעולות הגדר i באיזה מחלקה יש להגדיר אותה #C את הכותרת שלה ב- ii iii התיעוד שלה )מה הקלט, מה הפלט ובאיזה תנאי הפעולה תעבוד( ג. כתוב פעולה ב-# C המחזירה את מספר הסקרים בהם השתתפו יותר מ- 1000 משתתפים. באיזה מחלקה מהחמחלקות שהגדרת בסעיף א' יש להגדיר את הפעולה. הנח שפעולות set / get מוגדרים עבור כל המאפיינים של המחלקות שהגדרת בסעיף א. )הערה שלי- ניתן להוסיף פעולות רק יש להגדיר אותם ולממש אותם ולציין באיזה מחלקה הגדרת אותה(
תרגיל 2 לפניך מחלקת Worker class Worker שם העובד name;// private string באיזה מחלקה עובד// dept; private (1) שנה בה התחיל לעבוד // yearbeginwork; private int public Worker(string name, Dept dept) this.name = name; this.dept = dept; this.yearbeginwork = System.DateTime.Now.Year; רושם את השנה הנוכחי // public string GetName() return this.name; public ( 2 ) GetDept() return this.dept; public int GetBeginYear() return this.yearbeginwork; public int GetSenioriyInYears() return System.DateTime.Now.Year - yearbeginwork; חישוב שנות ותק // public void SetName(string name) אין לשנות את השם אם המחרוזת ריקה // if (this.name.trim().length > 0) this.name = name; public void SetDept(Dept dept) this.dept = dept; return string.format("worker : 0 in department 1 and has been working for 2 years", name, dept.getname(), GetSenioriyInYears()); ומחלקת מחלקה : המכיל שם המחלקה, הבוס )הכלה של Worker כי המנהל הוא אובייקט מסוג worker class Dept private string deptname; private int count; private Worker[] workers; private Worker boss; public Dept(string deptname, Worker boss) this.deptname = deptname; workers = new Worker[20]; count = 0; this.boss = boss; public Dept(string deptname):this (deptname,null) public string GetName() return this.deptname;
public void AddWorker(Worker w) Dept temp = w.getdept(); if (temp == null) ( 3 ) ; w.setdept( ( 4 ) ); workers[count++] = w; public void RemoveWorker(Worker w) int i; bool found = false; for (i = 0; ( 5 ) ; i++) found = workers[i] == w; if (found) for (; i < count-1; i++) ( 6 ) ; workers[--count] = null; public int FindWorker(Worker w) כתוב פעולה המחפשת עובד ומחזיר (++i את count; המספר> ;0 i הסידורי = שלוi החל (int מ- for0 כראשון. if (workers[i] == w) אם העובד אינו נמצא הפעולה תחזיר 1- ;i return return -1; public int GetNoOfWorkers() return count; string s = "Department Name : " + deptname + " and is lead by " + boss.getname(); for (int i = 0; i < count; i++) s += "\n" + workers[i].tostring(); return s; public int CountOverYearsSeniority(int years) כתוב פעולה המחזירה כמה עובדים יש במחלקה שיש להם ותק של Years שנים ויותר. עבור התרגיל יש להשלים את ששת הביטויים ולכתוב את שתי הפעולות החסרות.